#include "GEnginePCH.h"
#include "Entity.h"
#include "Model.h"
#include "D3DApp.h"
#include "Support.h"
#include "Shaders.h"
#include "Camera.h"

Entity::Entity( Model *m )
{
	model = m;
	m_vDir = D3DXVECTOR3(0,0,0);
	velocity = 22.3f;
}

Entity::~Entity(void)
{
}
Model* Entity::GetModel(void)
{
	return model;
}
void Entity::Render(void)
{
	model->Render();
}
void Destructible::RenderHP( const D3DXMATRIX& matVP, Camera* camera )
{
	
	int k=0;

	COLORED_VERTEX *pVertices = NULL;
	short *pIndices = NULL;

	VB->Lock( 0, sizeof(COLORED_VERTEX), (void**)&pVertices, 0 );
	IB->Lock( 0, 6*sizeof(short), (void**)&pIndices, 0 );
	
	D3DXMATRIX matBillboard, matViewTrans, matW, matS, matR ;
	// Create billboard matrix

	D3DXMATRIX matView = camera->GetMat();
	D3DXMatrixTranspose(&matViewTrans, &matView);
	D3DXMatrixIdentity(&matBillboard);
	matBillboard._11 = matViewTrans._11;
	matBillboard._12 = matViewTrans._12;
	matBillboard._13 = matViewTrans._13;
	matBillboard._21 = matViewTrans._21;
	matBillboard._22 = matViewTrans._22;
	matBillboard._23 = matViewTrans._23;
	matBillboard._31 = matViewTrans._31;
	matBillboard._32 = matViewTrans._32;
	matBillboard._33 = matViewTrans._33;

	D3DXMatrixTranslation(&matW, m_vPos.x, m_vPos.y + GetModel()->maxB.y * m_vScale.y + 1.1f, m_vPos.z);
	D3DXMatrixScaling(&matS, (GetModel()->maxB.x-GetModel()->minB.x) * m_vScale.x/2.0f, 0.7f, 1.0f );
	D3DXMatrixRotationZ(&matR, camera->vRot.z);
	matBillboard = matS * matR * matBillboard * matW;

	float percentage = ((float)HP)/maxHP;
	DWORD color = (DWORD)D3DXCOLOR(1.0f * (1 - percentage),1.0f * percentage,0.0f,1.0f);
	D3DXVECTOR3 vTmp;
	vTmp.x = -1.0f * percentage;
	vTmp.y = 1.0f;
	vTmp.z = 0.0f;

	D3DXVECTOR4 vTmp4;
	D3DXVec3Transform( &vTmp4, &vTmp, &matBillboard);


	pVertices->x = vTmp4.x;
	pVertices->y = vTmp4.y;
	pVertices->z = vTmp4.z;
	pVertices->color = color;
	pVertices++;


	vTmp.x = 1.0f * percentage;
	vTmp.y = 1.0f;
	vTmp.z = 0.0f;
	D3DXVec3Transform( &vTmp4, &vTmp, &matBillboard);


	pVertices->x = vTmp4.x;
	pVertices->y = vTmp4.y;
	pVertices->z = vTmp4.z;
	pVertices->color = color;
	pVertices++;

	vTmp.x = -1.0f * percentage;
	vTmp.y = -1.0f;
	vTmp.z = 0.0f;
	D3DXVec3Transform( &vTmp4, &vTmp, &matBillboard);


	pVertices->x = vTmp4.x;
	pVertices->y = vTmp4.y;
	pVertices->z = vTmp4.z;
	pVertices->color = color;
	pVertices++;

	vTmp.x = 1.0f * percentage;
	vTmp.y = -1.0f;
	vTmp.z = 0.0f;
	D3DXVec3Transform( &vTmp4, &vTmp, &matBillboard);


	pVertices->x = vTmp4.x;
	pVertices->y = vTmp4.y;
	pVertices->z = vTmp4.z;
	pVertices->color = color;
	pVertices++;

	*pIndices++ =(short)( k  );  //v0
	*pIndices++ =(short)( k+1 ); //v1 
	*pIndices++ =(short)( k+2 ); //v2 

	*pIndices++ =(short)( k+1  ); //v1
	*pIndices++ =(short)( k+3 );  //v3 
	*pIndices++ =(short)( k+2 );  //v2 

	VB->Unlock();
	IB->Unlock();
	

	D3DXMATRIX matWVP,matVPTransposed;
	D3DXMatrixTranspose(&matVPTransposed, &matVP);
	d3ddev->SetVertexShaderConstantF(0, matVPTransposed, 4);	
	d3ddev->SetVertexDeclaration(Shaders::getVertexDeclaration(3));
	d3ddev->SetPixelShader(Shaders::getPixelShader(4));
	d3ddev->SetVertexShader(Shaders::getVertexShader(3));
	d3ddev->SetIndices(IB);		
	d3ddev->SetStreamSource( 0, VB, 0, sizeof(COLORED_VERTEX) );	

	HRESULT hr;
	if(FAILED(hr = d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0,
		4, 0, 2 )))
	{
		MessageBox(0, "RenderHP failed !", 0, 0);
	}

}
void Destructible::RestoreDeviceObjects()
{

	d3ddev->CreateVertexBuffer( 4*sizeof(COLORED_VERTEX), D3DUSAGE_WRITEONLY, 
		NULL, D3DPOOL_DEFAULT, 
		&VB, NULL );


	d3ddev->CreateIndexBuffer( 6*sizeof(short),D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_DEFAULT,&IB,NULL);
	
}
void Warrior::RestoreDeviceObjects()
{
	Destructible::RestoreDeviceObjects();
	d3ddev->CreateVertexBuffer( 4*sizeof(POSITION_VERTEX), D3DUSAGE_WRITEONLY, 
		NULL, D3DPOOL_DEFAULT, 
		&VBs, NULL );


	d3ddev->CreateIndexBuffer( 6*sizeof(short),D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_DEFAULT,&IBs,NULL);
}
void Destructible::InvalidateDeviceObjects()
{
	if( VB != NULL )
	{
		int nNewRefCount =	VB->Release();

		if( nNewRefCount > 0 )
		{
			static char strError[255];
			sprintf_s( strError, "The Destructible HP Vertex Buffer object failed to cleanup properly.\n"
				"Release() returned a reference count of %d", nNewRefCount );
			MessageBox( NULL, strError, "ERROR", MB_OK | MB_ICONEXCLAMATION );
		}

		VB = NULL;
	}

	if( IB != NULL )
	{
		int nNewRefCount = IB->Release();

		if( nNewRefCount > 0 )
		{
			static char strError[255];
			sprintf_s( strError, "The Destructible HP Index Buffer object failed to cleanup properly.\n"
				"Release() returned a reference count of %d", nNewRefCount );
			MessageBox( NULL, strError, "ERROR", MB_OK | MB_ICONEXCLAMATION );
		}

		IB = NULL;
	}
}
void Warrior::InvalidateDeviceObjects()
{
	Destructible::InvalidateDeviceObjects();
	if( VBs != NULL )
	{
		int nNewRefCount =	VBs->Release();

		if( nNewRefCount > 0 )
		{
			static char strError[255];
			sprintf_s( strError, "The Warrior Stats Vertex Buffer object failed to cleanup properly.\n"
				"Release() returned a reference count of %d", nNewRefCount );
			MessageBox( NULL, strError, "ERROR", MB_OK | MB_ICONEXCLAMATION );
		}

		VBs = NULL;
	}

	if( IBs != NULL )
	{
		int nNewRefCount = IBs->Release();

		if( nNewRefCount > 0 )
		{
			static char strError[255];
			sprintf_s( strError, "The Warrior Stats Index Buffer object failed to cleanup properly.\n"
				"Release() returned a reference count of %d", nNewRefCount );
			MessageBox( NULL, strError, "ERROR", MB_OK | MB_ICONEXCLAMATION );
		}

		IBs = NULL;
	}
}

void Warrior::RenderStats()
{

	int k=0;

	POSITION_VERTEX *pVertices = NULL;
	short *pIndices = NULL;

	VBs->Lock( 0, sizeof(POSITION_VERTEX), (void**)&pVertices, 0 );
	IBs->Lock( 0, 6*sizeof(short), (void**)&pIndices, 0 );

	
	pVertices->x =  0.6f;
	pVertices->y =  -0.6f;
	pVertices->z =  1.0f;
	pVertices++;

	pVertices->x =  1.0f;
	pVertices->y =  -0.6f;
	pVertices->z =  1.0f;
	pVertices++;

	pVertices->x =  0.6f;
	pVertices->y =  -1.0f;
	pVertices->z =  1.0f;
	pVertices++;

	pVertices->x =  1.0f;
	pVertices->y =  -1.0f;
	pVertices->z =  1.0f;
	pVertices++;


	*pIndices++ =(short)( k  );  //v0
	*pIndices++ =(short)( k+1 ); //v1 
	*pIndices++ =(short)( k+2 ); //v2 

	*pIndices++ =(short)( k+1  ); //v1
	*pIndices++ =(short)( k+3 );  //v3 
	*pIndices++ =(short)( k+2 );  //v2 

	VBs->Unlock();
	IBs->Unlock();     

	d3ddev->SetVertexDeclaration(Shaders::getVertexDeclaration(4));
	d3ddev->SetPixelShader(Shaders::getPixelShader(5));
	d3ddev->SetVertexShader(Shaders::getVertexShader(4));
	d3ddev->SetIndices(IBs);		
	d3ddev->SetStreamSource( 0, VBs, 0, sizeof(POSITION_VERTEX) );	

	HRESULT hr;
	if(FAILED(hr = d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0,
		4, 0, 2 )))
	{
		MessageBox(0, "RenderStats failed !", 0, 0);
	} 
	

	LPD3DXFONT myFont;	
	D3DXCreateFont( d3ddev, 20, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &myFont );

	D3DCOLOR fontColor = D3DCOLOR_ARGB(255,255,0,0);   

	// Create a rectangle to indicate where on the screen it should be drawn
	RECT rct;
	rct.left=SCREEN_WIDTH-140;
	rct.right=SCREEN_WIDTH;
	rct.top=SCREEN_HEIGHT-140;
	rct.bottom=rct.top+20;

	// Draw some text
	char c[200];	
	sprintf_s(c,"HP  : %d / %d ", HP, maxHP);
	myFont->DrawText(NULL, c, -1, &rct, 0, fontColor );
	rct.top += 30;
	rct.bottom += 30;
	sprintf_s(c,"Damage : %d ",damage);
	myFont->DrawText(NULL, c, -1, &rct, 0, fontColor );
	sprintf_s(c,"Armor  : %d ",armor);
	rct.top += 30;
	rct.bottom += 30;
	myFont->DrawText(NULL, c, -1, &rct, 0, fontColor );
	myFont->Release();
}

void Entity::Update(long deltaTime)
{	
	//m_vDir.x = DistanceSquared2D( m_vTarget, m_vPos ) ;
	//printVector(m_vDir);
	if( DistanceSquared2D( m_vTarget, m_vPos ) < 0.1f) return;
	
	
	m_vPos += velocity * m_vDir * (deltaTime/1000.0f);
}